/**
 * 备份功能测试脚本 - 检查是否能备份所有数据库表
 */
require('dotenv').config();
const mongoose = require('mongoose');
const path = require('path');
const fs = require('fs');
const { spawn } = require('child_process');
const moment = require('moment');
const config = require('../src/config/config');
const logger = require('../src/config/logger');

// 连接数据库
mongoose.connect(config.mongoose.url, config.mongoose.options).then(() => {
  console.log('成功连接到MongoDB');
  runTest();
}).catch(err => {
  console.error('MongoDB连接失败:', err);
  process.exit(1);
});

// 获取所有集合
async function getAllCollections() {
  try {
    const collections = await mongoose.connection.db.collections();
    return collections.map(collection => collection.collectionName);
  } catch (error) {
    console.error('获取集合失败:', error);
    return [];
  }
}

// 内置方法备份数据库
async function backupUsingNative() {
  try {
    const timestamp = moment().format('YYYY-MM-DD_HH-mm-ss');
    const backupFileName = `test_backup_${timestamp}.json`;
    const relativePath = `/backups/${backupFileName}`;
    const fullPath = path.join(__dirname, '../', relativePath);
    
    // 确保备份目录存在
    const backupDir = path.dirname(fullPath);
    if (!fs.existsSync(backupDir)) {
      fs.mkdirSync(backupDir, { recursive: true });
    }
    
    console.log(`开始备份到文件: ${fullPath}`);
    
    // 获取所有集合
    const collections = await mongoose.connection.db.collections();
    
    // 创建导出数据对象
    const exportData = {
      metadata: {
        exportDate: new Date(),
        version: '1.0',
        database: mongoose.connection.name
      },
      collections: {}
    };
    
    // 记录备份前的集合数量
    console.log(`数据库中总共有 ${collections.length} 个集合`);
    console.log('集合列表:');
    
    // 对每个集合导出数据并计算文档数量
    for (const collection of collections) {
      const collectionName = collection.collectionName;
      
      // 获取集合中的所有文档
      const documents = await collection.find({}).toArray();
      
      exportData.collections[collectionName] = documents;
      console.log(`- ${collectionName}: ${documents.length} 条文档`);
    }
    
    // 写入到文件
    const jsonData = JSON.stringify(exportData, null, 2);
    fs.writeFileSync(fullPath, jsonData);
    
    // 计算文件大小（KB）
    const stats = fs.statSync(fullPath);
    const fileSizeInKB = Math.ceil(stats.size / 1024);
    
    console.log(`备份完成，文件大小: ${fileSizeInKB}KB`);
    
    // 验证备份文件是否包含所有集合
    verifyBackup(fullPath, collections.length);
    
    return fullPath;
  } catch (error) {
    console.error('备份失败:', error);
    return null;
  }
}

// 验证备份文件是否包含所有集合
function verifyBackup(backupPath, expectedCollectionCount) {
  try {
    // 读取备份文件
    const jsonData = fs.readFileSync(backupPath, 'utf8');
    const backupData = JSON.parse(jsonData);
    
    // 检查集合数量
    const actualCollectionCount = Object.keys(backupData.collections).length;
    
    console.log('\n备份验证结果:');
    console.log(`- 预期集合数量: ${expectedCollectionCount}`);
    console.log(`- 实际备份集合数量: ${actualCollectionCount}`);
    
    if (actualCollectionCount === expectedCollectionCount) {
      console.log('✅ 验证通过: 所有集合都已被备份');
    } else {
      console.log('❌ 验证失败: 备份集合数量与实际不符');
      
      // 输出缺少的集合
      getAllCollections().then(allCollections => {
        const backupCollections = Object.keys(backupData.collections);
        const missingCollections = allCollections.filter(name => !backupCollections.includes(name));
        
        if (missingCollections.length > 0) {
          console.log('缺少的集合:');
          missingCollections.forEach(name => console.log(`- ${name}`));
        }
      });
    }
  } catch (error) {
    console.error('验证备份失败:', error);
  }
}

// 运行测试
async function runTest() {
  try {
    console.log('开始测试备份功能...');
    
    // 获取所有集合
    const collections = await getAllCollections();
    console.log(`数据库中总共有 ${collections.length} 个集合:`);
    collections.forEach(name => console.log(`- ${name}`));
    
    // 使用内置方法进行备份
    const backupPath = await backupUsingNative();
    
    if (backupPath) {
      console.log('\n备份成功完成并验证!');
    } else {
      console.log('\n备份失败!');
    }
    
    // 断开数据库连接
    mongoose.disconnect();
  } catch (error) {
    console.error('测试过程出错:', error);
    mongoose.disconnect();
  }
} 